package cn.com.ry.framework.mongodb.adatper.mysql;

import com.alibaba.fastjson.JSON;
import cn.com.ry.framework.mongodb.adatper.util.MongoDBToMysqlTool;
import cn.com.ry.framework.mongodb.adatper.util.ValueFilterTool;
import com.mongodb.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.CollectionOptions;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoWriter;
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

public class MongoAdapterTemplate extends MongoTemplate {

    private static final Logger LOGGER = LoggerFactory.getLogger(MongoAdapterTemplate.class);

    protected JdbcTemplate jdbcTemplateMongo;

    private static String tableName = "";

    private String dbName = "";

    public MongoAdapterTemplate(MongoDbFactory mongoDbFactory, String databaseName, JdbcTemplate jdbcTemplate) {
        super(mongoDbFactory);
        this.dbName = databaseName;
        this.jdbcTemplateMongo = jdbcTemplate;
    }

    public JdbcTemplate getJdbcTemplateMongo() {
        return jdbcTemplateMongo;
    }

    public void setJdbcTemplateMongo(JdbcTemplate jdbcTemplateMongo) {
        this.jdbcTemplateMongo = jdbcTemplateMongo;
    }

    public String getDbName() {
        return dbName;
    }

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }

    /**
     * 为属性自动注入bean服务
     *
     * @param jdbcTemplateMongo
     */
    public void setjdbcTemplateMongo(JdbcTemplate jdbcTemplateMongo) {
        this.jdbcTemplateMongo = jdbcTemplateMongo;
    }


    /**
     * 将类转成表
     *
     * @param clazz
     * @return
     */
    public String getCollectionName(Class<?> clazz) {
        if (clazz == null) {
            return "";
        }
        String className = clazz.getSimpleName();
        char[] chars = new char[1];
        chars[0] = className.charAt(0);
        String temp = new String(chars);
        if (chars[0] >= 'A' && chars[0] <= 'Z') {//当为字母时，则转换为小写
            return className.replaceFirst(temp, temp.toLowerCase());
        } else {
            return "";
        }
    }

    /**
     * 返回所以表列表
     *
     * @return
     */
    public Set<String> getCollectionNames() {
        String sql = "select table_name as tableName from information_schema.TABLES where TABLE_SCHEMA='" + dbName + "'";
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("[getCollectionNames]," + sql);
        }
        List<String> data = jdbcTemplateMongo.query(sql, new RowMapper<String>() {
            public String mapRow(ResultSet rs, int rowNum) throws SQLException {
                return rs.getString(1);
            }

        }, null);

        return new HashSet(data);
    }


    /**
     * 删除collection
     *
     * @param clazz
     * @return
     */
    public <T> void dropCollection(Class<T> clazz) {
        if (clazz != null) {
            dropCollection(getCollectionName(clazz));
        }
    }

    public void dropCollection(String tableName) {
        if (tableName != null && !tableName.trim().equals("")) {
            String sql = "drop table " + tableName;
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[dropCollection]," + sql);
            }
            jdbcTemplateMongo.execute(sql);
        }
    }

    /**
     * 系统中没有该方法 ，TODO
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> DBCollection createCollection(Class<T> clazz) {
        return createCollection(tableName, null);
    }

    public <T> DBCollection createCollection(Class<T> clazz, CollectionOptions collectionOptions) {
        if (clazz != null) {
            String tableName = getCollectionName(clazz);
            return createCollection(tableName, null);
        }

        return null;
    }

    public DBCollection createCollection(String tableName) {
        return createCollection(tableName, null);
    }

    public DBCollection createCollection(String tableName, CollectionOptions collectionOptions) {
        if (tableName != null && !tableName.trim().equals("")) {
            String sql = "CREATE TABLE `" + tableName + "` (\n" +
                    "  `id` int(11) NOT NULL AUTO_INCREMENT,\n" +
                    "  `datajson` json DEFAULT NULL,\n" +
                    "  PRIMARY KEY (`id`)\n" +
                    ") ";
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[createCollection]," + sql);
            }
            jdbcTemplateMongo.execute(sql);
        }
        return null;
    }

    public <T> List<T> find(Query query, Class<T> clazz) {
        List result = new ArrayList<>();
        if (clazz != null && clazz != null) {
            //获取表名
            String tableName = getCollectionName(clazz);
            result = find(query, clazz, tableName);
        }
        return result;
    }

    public <T> List<T> find(Query query, Class<T> clazz, String tableName) {
        List result = new ArrayList<>();
        if (clazz != null || tableName != null) {
            //获取表名
            if (tableName == null || tableName.trim().equals("")) {
                tableName = getCollectionName(clazz);
            }
            String sql = MongoDBToMysqlTool.mongoDBToMysqlForFind(tableName, MongoDBToMysqlTool.COLUMN_NAME, query);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[find]," + query.getQueryObject());
                LOGGER.debug("[find]," + sql);
            }
            try {
                List<String> dataList = jdbcTemplateMongo.queryForList(sql, String.class);
                if (dataList != null && dataList.size() > 0) {
                    for (int i = 0; i < dataList.size(); i++) {
                        String data = dataList.get(i);
                        result.add(JSON.parseObject(data, clazz));
                    }
                }
            } catch (Exception e) {
                LOGGER.error("sql执行异常,sql=" + sql, e);
            }

        }
        return result;
    }

    public <T> List<T> findAll(Class<T> clazz) {
        List<T> result = new ArrayList<>();
        if (clazz != null) {
            //获取表名
            String tableName = getCollectionName(clazz);
            return findAll(clazz, tableName);
        }
        return result;
    }

    public <T> List<T> findAll(Class<T> clazz, String tableName) {
        List<T> result = new ArrayList<>();
        if (clazz != null || tableName != null) {
            //获取表名
            if (tableName == null || tableName.trim().equals("")) {
                tableName = getCollectionName(clazz);
            }
            String sql = "select " + MongoDBToMysqlTool.COLUMN_NAME + " from " + tableName;
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[findAll]," + sql);
            }
            try {
                List<String> dataList = jdbcTemplateMongo.queryForList(sql, String.class);
                if (dataList != null && dataList.size() > 0) {
                    for (int i = 0; i < dataList.size(); i++) {
                        String data = dataList.get(i);
                        result.add(JSON.parseObject(data, clazz));
                    }
                }
            } catch (Exception e) {
                LOGGER.error("sql执行失败，sql=" + sql, e);
            }

        }
        return result;
    }

    public <T> T findAndModify(Query query, Update update, Class<T> clazz) {
        return findAndModify(query, update, new FindAndModifyOptions(), clazz);
    }

    public <T> T findAndModify(Query query, Update update, Class<T> clazz, String tableName) {
        return findAndModify(query, update, new FindAndModifyOptions(), clazz, tableName);
    }

    public <T> T findAndModify(Query query, Update update, FindAndModifyOptions findAndModifyOptions, Class<T> clazz) {
        if (clazz != null) {
            String tableName = getCollectionName(clazz);
            return findAndModify(query, update, findAndModifyOptions, clazz, tableName);
        } else {
            return null;
        }
    }

    public <T> T findAndModify(Query query, Update update, FindAndModifyOptions findAndModifyOptions, Class<T> clazz, String tableName) {
        if (clazz != null && (tableName == null || tableName.trim().equals(""))) {
            tableName = getCollectionName(clazz);
        }
        DBObject dbObject = update.getUpdateObject();
        if (dbObject == null) {
            return (T) clazz;
        }
        String dataJson = "";
        String updateSql = MongoDBToMysqlTool.mongoDBToMysqlForUpdate(tableName, query, update);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("[findAndModify]," + query.getQueryObject());
            LOGGER.debug("[findAndModify]," + updateSql);
        }
        int t = jdbcTemplateMongo.update(updateSql);
        try {
            t = jdbcTemplateMongo.update(updateSql);
        } catch (Exception e) {
            LOGGER.error("sql执行失败，sql=" + updateSql, e);
        }
        if (t <= 0) {
            JSON.toJSONString(dbObject, ValueFilterTool.getValueFilter());

            //兼容mongodbId
            ValueFilterTool.getMongoDBMap(dbObject.toMap());

            String mongoId = (String) dbObject.get("_id");
            //如果_id不存在则生成一个
            if (mongoId == null) {
                mongoId = UUID.randomUUID().toString().replace("-", "");
                dbObject.put("_id", mongoId);
            }
            dataJson = JSON.toJSONString(dbObject, ValueFilterTool.getValueFilter());
            String insertSql = "insert into " + tableName + "(" + MongoDBToMysqlTool.COLUMN_NAME + ") values(?)";
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[findAndModify]," + query.getQueryObject());
                LOGGER.debug("[findAndModify]," + insertSql);
            }
            try {
                jdbcTemplateMongo.update(insertSql, dataJson);
            } catch (Exception e) {
                LOGGER.error("sql执行失败，sql=" + insertSql, e);
            }

        }
        return (T) JSON.parseObject(dataJson, clazz);
    }

    /**
     * TODO 项目未使用，暂不实现
     *
     * @param query
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T findAndRemove(Query query, Class<T> clazz) {
        return null;
    }

    public <T> T findAndRemove(Query query, Class<T> clazz, String tableName) {
        return null;
    }

    /**
     * 通过ID查询
     *
     * @param id
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T findById(Object id, Class<T> clazz) {
        if (clazz != null) {
            String tableName = getCollectionName(clazz);
            return findById(id, clazz, tableName);
        }
        return null;
    }

    public <T> T findById(Object id, Class<T> clazz, String tableName) {
        if (clazz != null) {
            if (tableName == null || tableName.trim().equals("")) {
                tableName = getCollectionName(clazz);
            }
            String sql = "select datajson from " + tableName + " where _id='" + id + "'";
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[findById]," + sql);
            }
            try {
                List<String> dataList = jdbcTemplateMongo.queryForList(sql, String.class);
                if (dataList != null && dataList.size() > 0) {
                    return (T) JSON.parseObject(dataList.get(0), clazz);
                }
            } catch (Exception e) {
                LOGGER.error("sql执行失败，sql=" + sql, e);
            }

        }
        return null;
    }

    /**
     * 查询一条记录
     *
     * @param query
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T findOne(Query query, Class<T> clazz) {
        if (query != null && clazz != null && clazz != null) {
            //获取表名
            String tableName = getCollectionName(clazz);
            return findOne(query, clazz, tableName);
        }
        return null;
    }

    public <T> T findOne(Query query, Class<T> clazz, String tableName) {
        if (query != null && (clazz != null || tableName != null)) {
            query.limit(1);
            query.skip(0);
            //获取表名
            if (tableName == null || tableName.trim().equals("")) {
                tableName = getCollectionName(clazz);
            }
            String sql = MongoDBToMysqlTool.mongoDBToMysqlForFind(tableName, MongoDBToMysqlTool.COLUMN_NAME, query);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[findOne]," + query.getQueryObject());
                LOGGER.debug("[findOne]," + sql);
            }
            try {
                List<String> dataList = jdbcTemplateMongo.queryForList(sql, String.class);
                if (dataList != null && dataList.size() > 0) {
                    return (T) JSON.parseObject(dataList.get(0), clazz);

                }
            } catch (Exception e) {
                LOGGER.error("sql执行失败，sql=" + sql, e);
            }

        }
        return null;
    }

    /**
     * 插入，如果ID重复就报错
     *
     * @param data
     * @param clazz
     */
    public void insert(Collection<? extends Object> data, Class<?> clazz) {
        if (data != null && !data.isEmpty() && clazz != null) {
            //获取表名
            String tableName = getCollectionName(clazz);
            insert(data, tableName);
        }
    }

    public void insert(Collection<? extends Object> data, String tableName) {
        if (data != null && !data.isEmpty() && tableName != null && !tableName.trim().equals("")) {
            insertAll(data, tableName);
        }
    }

    /**
     * 插入一条数据
     *
     * @param model
     */
    public void insert(Object model) {
        if (model != null) {
            Class clazz = model.getClass();
            //获取表名
            String tableName = getCollectionName(clazz);
            insert(model, tableName);
        }
    }

    public void insert(Object model, String tableName) {
        if (model != null) {
            Class clazz = model.getClass();
            //获取表名
            if (tableName == null || tableName.trim().equals("")) {
                tableName = getCollectionName(clazz);
            }
            //转换成sql
            String sql = "insert into " + tableName + "(" + MongoDBToMysqlTool.COLUMN_NAME + ") values(?)";
            //获取_id
            String dataJson = JSON.toJSONString(model, ValueFilterTool.getValueFilter());
            Map dataJsonMap = (Map) JSON.parse(dataJson);

            //兼容mongodbId
            ValueFilterTool.getMongoDBMap(dataJsonMap);

            String mongoId = (String) dataJsonMap.get("_id");
            //如果_id不存在则生成一个
            if (mongoId == null) {
                mongoId = UUID.randomUUID().toString().replace("-", "");
                dataJsonMap.put("_id", mongoId);
            }
            dataJson = JSON.toJSONString(dataJsonMap, ValueFilterTool.getValueFilter());
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[insert]," + sql);
            }
            try {
                jdbcTemplateMongo.update(sql, new Object[]{dataJson});
            } catch (Exception e) {
                LOGGER.error("sql执行失败，sql=" + sql, e);
            }

        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void insertAll(Collection<? extends Object> data) {
        if (data != null && data.size() > 0) {
            Iterator it = data.iterator();
            for (; it.hasNext(); ) {
                Object object = it.next();
                String sql = "";
                if (object != null) {
                    String tableName = getCollectionName(object.getClass());
                    String dataJson = JSON.toJSONString(object, ValueFilterTool.getValueFilter());
                    Map dataJsonMap = JSON.parseObject(dataJson, Map.class);
                    //兼容mongodbId
                    ValueFilterTool.getMongoDBMap(dataJsonMap);
                    //判断dataMap中id是否存在值
                    String mongoId = (String) dataJsonMap.get("_id");
                    if (mongoId == null) {
                        mongoId = UUID.randomUUID().toString().replace("-", "");
                        dataJsonMap.put("_id", mongoId);
                    }
                    dataJson = JSON.toJSONString(dataJsonMap, ValueFilterTool.getValueFilter());
                    sql = "insert into " + tableName + " (datajson) value('" + dataJson + "')";
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("[insertAll]," + sql);
                    }
                    try {
                        jdbcTemplateMongo.update(sql);
                    } catch (Exception e) {
                        LOGGER.error("sql执行失败，sql=" + sql, e);
                    }

                }
            }
        }
    }


    @Transactional(propagation = Propagation.REQUIRED)
    public void insertAll(Collection<? extends Object> data, String tableName) {
        if (data != null && data.size() > 0 && tableName != null) {
            Iterator it = data.iterator();
            for (; it.hasNext(); ) {
                Object object = it.next();
                String sql = "";
                if (object != null) {
                    String dataJson = JSON.toJSONString(object, ValueFilterTool.getValueFilter());
                    Map dataJsonMap = JSON.parseObject(dataJson, Map.class);
                    //兼容mongodbId
                    ValueFilterTool.getMongoDBMap(dataJsonMap);
                    //判断dataMap中id是否存在值
                    String mongoId = (String) dataJsonMap.get("_id");
                    if (mongoId == null) {
                        mongoId = UUID.randomUUID().toString().replace("-", "");
                        dataJsonMap.put("_id", mongoId);
                    }
                    dataJson = JSON.toJSONString(dataJsonMap, ValueFilterTool.getValueFilter());
                    sql = "insert into " + tableName + " (datajson) value('" + dataJson + "')";
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("[insert]," + sql);
                    }
                    try {
                        jdbcTemplateMongo.update(sql);
                    } catch (Exception e) {
                        LOGGER.error("sql执行失败，sql=" + sql, e);
                    }

                }
            }
        }
    }


    public <T> MapReduceResults<T> mapReduce(Query query, String collectionName, String mapFun, String reduceFun, MapReduceOptions mapReduceOptions, Class<T> clazz) {
        return new MapReduceResults(new ArrayList(), new BasicDBObject());
    }

    public <T> MapReduceResults<T> mapReduce(Query query, String collectionName, String mapFun, String reduceFun, Class<T> clazz) {
        return mapReduce(query, collectionName, mapFun, reduceFun, null, clazz);

    }

    public <T> MapReduceResults<T> mapReduce(String collectionName, String mapFun, String reduceFun, Class<T> clazz) {
        return mapReduce(collectionName, mapFun, reduceFun, null, clazz);
    }

    public <T> MapReduceResults<T> mapReduce(String collectionName, String mapFun, String reduceFun, MapReduceOptions mapReduceOptions, Class<T> clazz) {
        return mapReduce(null, collectionName, mapFun, reduceFun, mapReduceOptions, clazz);

    }


    public WriteResult remove(Object data) {
        if (data != null) {
            String tableName = getCollectionName(data.getClass());
            return remove(data, tableName);
        } else {
            return null;
        }
    }

    public WriteResult remove(Object data, String tableName) {
        if (data != null) {
            if (tableName == null || tableName.trim().equals("")) {
                tableName = getCollectionName(data.getClass());
            }
            String dataJson = JSON.toJSONString(data, ValueFilterTool.getValueFilter());
            Map dataJsonMap = JSON.parseObject(dataJson, Map.class);
            //兼容mongodbId
            ValueFilterTool.getMongoDBMap(dataJsonMap);
            //判断dataMap中id是否存在值
            String mongoId = (String) dataJsonMap.get("_id");
            if (mongoId != null) {
                Query query = new Query().addCriteria(new Criteria("_id").is(mongoId));
                return remove(query, tableName);
            }
        }
        return null;
    }

    public WriteResult remove(Query query, Class<?> clazz) {
        //获取表名
        if (clazz != null) {
            String tableName = getCollectionName(clazz);
            return remove(query, clazz, tableName);
        } else {
            return null;
        }
    }

    public WriteResult remove(Query query, Class<?> clazz, String tableName) {
        //获取表名
        if (clazz != null || tableName != null) {
            //获取表名
            if (tableName == null || tableName.trim().equals("")) {
                tableName = getCollectionName(clazz);
            }
            String sql = MongoDBToMysqlTool.mongoDBToMysqlForDel(tableName, MongoDBToMysqlTool.COLUMN_NAME, query);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[remove]," + query.getQueryObject());
                LOGGER.debug("[remove]," + sql);
            }
            try {
                jdbcTemplateMongo.update(sql);
            } catch (Exception e) {
                LOGGER.error("sql执行失败，sql=" + sql, e);
            }

        }
        return null;
    }

    public WriteResult remove(Query query, String tableName) {
        //获取表名
        if (tableName != null) {
            return remove(query, null, tableName);
        } else {
            return null;
        }
    }


    /**
     * 保存，如果_id的值不存在就插入，存在就更新
     *
     * @param model
     */
    public void save(Object model) {
        if (model != null) {
            //获取表名
            String tableName = getCollectionName(model.getClass());
            save(model, tableName);
        }
    }

    public void save(Object model, String tableName) {
        if (model != null) {
            //获取表名
            if (tableName == null || tableName.trim().equals("")) {
                tableName = getCollectionName(model.getClass());
            }
            //获取_id
            String dataJson = JSON.toJSONString(model, ValueFilterTool.getValueFilter());
            Map dataJsonMap = (Map) JSON.parse(dataJson);
            //兼容mongodbId
            ValueFilterTool.getMongoDBMap(dataJsonMap);

            String mongoId = (String) dataJsonMap.get("_id");
            String sql = "";
            //如果_id不存在则生成一个
            if (mongoId == null) {
                mongoId = UUID.randomUUID().toString().replace("-", "");
                dataJsonMap.put("_id", mongoId);
            }
            dataJson = JSON.toJSONString(dataJsonMap, ValueFilterTool.getValueFilter());

            sql = "select count(*) as count from " + tableName + " where _id= ?";
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[save]," + sql);
            }
            Map map = new HashMap();
            map.put("count", 0);
            try {
                map = jdbcTemplateMongo.queryForMap(sql, new Object[]{mongoId});
            } catch (Exception e) {
                LOGGER.error("sql执行失败，sql=" + sql, e);
            }

            Object totalCount = map.get("count");
            long count = 0;
            if (totalCount instanceof Integer) {
                count = ((Integer) totalCount).longValue();
            } else {
                count = (long) totalCount;
            }
            if (count > 0) {
                sql = "update " + tableName + " set " + MongoDBToMysqlTool.COLUMN_NAME + "=?  where _id = '" + mongoId + "'";
            } else {
                sql = "insert into " + tableName + "(" + MongoDBToMysqlTool.COLUMN_NAME + ") values (?)";
            }
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[save]," + sql);
            }
            try {
                jdbcTemplateMongo.update(sql, new Object[]{dataJson});
            } catch (Exception e) {
                LOGGER.error("sql执行失败，sql=" + sql, e);
            }
            //返回对象，并添加_id
            try {
                Class c = model.getClass();
                Field f = c.getDeclaredField("_id");
                f.setAccessible(true);
                f.set(model, mongoId);
            } catch (Exception e) {

            }

        }
    }


    /**
     * 更新
     *
     * @param query
     * @param update
     * @param clazz
     * @return
     */
    public synchronized WriteResult updateFirst(Query query, Update update, Class<?> clazz) {
        String tableName = getCollectionName(clazz);
        return updateFirst(query, update, clazz, tableName);
    }

    public synchronized WriteResult updateFirst(Query query, Update update, String tableName) {
        return updateFirst(query, update, null, tableName);
    }

    public synchronized WriteResult updateFirst(Query query, Update update, Class<?> clazz, String tableName) {
        if (tableName == null || tableName.trim().equals("")) {
            tableName = getCollectionName(clazz);
        }
        if (query != null && query.getQueryObject() != null) {
            String mongoSql = query.getQueryObject().toString();
            Map map = JSON.parseObject(mongoSql, Map.class);

            //兼容mongodbId
            ValueFilterTool.getMongoDBMap(map);

            if (map != null && !map.isEmpty()) {
                Set keySet = map.keySet();
                String updateSql = "";
                if (keySet.size() == 1 && map.get("_id") != null) {
                    updateSql = MongoDBToMysqlTool.mongoDBToMysqlForUpdateById(tableName, (String) map.get("_id"), update);
                } else {
                    updateSql = MongoDBToMysqlTool.mongoDBToMysqlForUpdate(tableName, query, update);
                }
                updateSql += " limit 1";
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("[updateFirst]," + query.getQueryObject());
                    LOGGER.debug("[updateFirst]," + updateSql);
                }

                try {
                    int t = jdbcTemplateMongo.update(updateSql);
                    //通过反射实例化mongodb，为了兼容mongoTemplate
                    ServerAddress serverAddress = new ServerAddress("127.0.0.1");
                    Class commandResultClass = CommandResult.class;
                    Constructor<?> commandConstructor = commandResultClass.getDeclaredConstructor(ServerAddress.class);
                    commandConstructor.setAccessible(true);
                    CommandResult commandResult = (CommandResult) commandConstructor.newInstance(serverAddress);
                    commandResult.put("n", t);

                    Class<?> writeResultClass = WriteResult.class;
                    Constructor<?> writeResultConstructor = writeResultClass.getDeclaredConstructor(CommandResult.class, WriteConcern.class);
                    writeResultConstructor.setAccessible(true);
                    return (WriteResult) writeResultConstructor.newInstance(commandResult, null);
                } catch (Exception e) {
                    LOGGER.error("sql执行失败，sql=" + updateSql, e);
                }
                return null;
            }
        }
        return null;
    }

    /**
     * TODO 项目中没有，不需要实现
     *
     * @param query
     * @param update
     * @param clazz
     * @return
     */
    public synchronized WriteResult updateMulti(Query query, Update update, Class<?> clazz) {
        String tableName = getCollectionName(clazz);
        return updateMulti(query, update, clazz, tableName);
    }

    public synchronized WriteResult updateMulti(Query query, Update update, String tableName) {
        return updateMulti(query, update, null, tableName);
    }

    public synchronized WriteResult updateMulti(Query query, Update update, Class<?> clazz, String tableName) {
        if (tableName == null || tableName.trim().equals("")) {
            tableName = getCollectionName(clazz);
        }
        if (query != null && query.getQueryObject() != null) {
            String mongoSql = query.getQueryObject().toString();
            Map map = JSON.parseObject(mongoSql, Map.class);
            //兼容mongodbId
            ValueFilterTool.getMongoDBMap(map);

            if (map != null && !map.isEmpty()) {
                Set keySet = map.keySet();
                String updateSql = "";
                if (keySet.size() == 1 && map.get("_id") != null) {
                    updateSql = MongoDBToMysqlTool.mongoDBToMysqlForUpdateById(tableName, (String) map.get("_id"), update);
                } else {
                    updateSql = MongoDBToMysqlTool.mongoDBToMysqlForUpdate(tableName, query, update);
                }

                try {
                    int t = jdbcTemplateMongo.update(updateSql);
                    //通过反射实例化mongodb，为了兼容mongoTemplate
                    ServerAddress serverAddress = new ServerAddress("127.0.0.1");
                    Class commandResultClass = CommandResult.class;
                    Constructor<?> commandConstructor = commandResultClass.getDeclaredConstructor(ServerAddress.class);
                    commandConstructor.setAccessible(true);
                    CommandResult commandResult = (CommandResult) commandConstructor.newInstance(serverAddress);
                    commandResult.put("n", t);

                    Class<?> writeResultClass = WriteResult.class;
                    Constructor<?> writeResultConstructor = writeResultClass.getDeclaredConstructor(CommandResult.class, WriteConcern.class);
                    writeResultConstructor.setAccessible(true);
                    return (WriteResult) writeResultConstructor.newInstance(commandResult, null);
                } catch (Exception e) {
                    LOGGER.error("sql执行失败，sql=" + updateSql, e);
                }
                return null;
            }
        }
        return null;
    }

    /**
     * TODO 代码中没有,暂且不实现，根据条件有就更新没有就插入
     *
     * @param query
     * @param update
     * @param clazz
     * @return
     */
    public synchronized WriteResult upsert(Query query, Update update, Class<?> clazz) {
        if (clazz != null) {
            return upsert(query, update, clazz, getCollectionName(clazz));
        }
        return null;
    }

    public synchronized WriteResult upsert(Query query, Update update, Class<?> clazz, String tableName) {
        return null;
    }

    public synchronized WriteResult upsert(Query query, Update update, String tableName) {
        if (tableName != null && !tableName.equals("")) {
            return upsert(query, update, null, tableName);
        }
        return null;
    }


    /**
     * 获取MysqlTempate对象
     * TODO  项目中位使用，暂不实现
     *
     * @param collectionName
     * @return
     */
    public synchronized DBCollection getCollection(String collectionName) {
        this.tableName = collectionName;

        return null;
    }


    public synchronized DBObject findAndModify(DBObject query, DBObject fields, DBObject sort, boolean remove, DBObject update, boolean returnNew, boolean upsert) {
        DBObject result = new BasicDBObject();
        if (query == null || update == null) {
            return null;
        }
        try {
            //获取query
            String idName = (String) query.get("name");
            //update
            String sql = "update " + this.tableName + " " +
                    "set " + MongoDBToMysqlTool.COLUMN_NAME + "=JSON_SET(" + MongoDBToMysqlTool.COLUMN_NAME + ",'$." + idName + "',CAST(" + MongoDBToMysqlTool.toMysqlCol(tableName, idName) + "+1 AS SIGNED)) " +
                    "where " + MongoDBToMysqlTool.toMysqlCol(tableName, "name") + "='" + idName + "'";
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[findAndModify]," + sql);
            }
            jdbcTemplateMongo.update(sql);
            sql = "select " + MongoDBToMysqlTool.COLUMN_NAME + " from " + this.tableName + " where " + MongoDBToMysqlTool.toMysqlCol(tableName, "name") + "='" + idName + "' limit 0,1";
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("[findAndModify]," + sql);
            }
            Map returnMap = jdbcTemplateMongo.queryForMap(sql);
            result.putAll(returnMap);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 获取长度
     *
     * @param query
     * @param clazz
     * @return
     */
    public long count(Query query, Class<?> clazz) {
        String tableName = getCollectionName(clazz);
        return count(query, clazz, tableName);
    }

    public long count(Query query, String tableName) {
        return count(query, null, tableName);
    }

    public long count(Query query, Class<?> clazz, String tableName) {
        if (tableName == null || tableName.trim().equals("")) {
            tableName = getCollectionName(clazz);
        }
        String sql = MongoDBToMysqlTool.mongoDBToMysqlForFindCount(tableName, MongoDBToMysqlTool.COLUMN_NAME, query);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("[count]," + query.getQueryObject());
            LOGGER.debug("[count],sql=" + sql);
        }
        Map map = new HashMap();
        map.put("count", 0);
        try {
            map = jdbcTemplateMongo.queryForMap(sql);
        } catch (Exception e) {
            LOGGER.error("sql执行失败，sql=" + sql, e);
        }

        Object totalCount = map.get("count");
        if (totalCount instanceof Integer) {
            return ((Integer) totalCount).longValue();
        } else {
            return (long) totalCount;
        }
    }

    public boolean exists(Query query, Class<?> entityClass) {
        return exists(query, entityClass, getCollectionName(entityClass));
    }

    public boolean exists(Query query, String collectionName) {
        return exists(query, null, collectionName);
    }

    public boolean exists(Query query, Class<?> entityClass, String collectionName) {
        if (query == null) {
            throw new InvalidDataAccessApiUsageException("Query passed in to exist can't be null");
        }
        if (findOne(query, entityClass, collectionName) != null) {
            return true;
        } else {
            return false;
        }
    }

    protected WriteResult doUpdate(final String collectionName, final Query query, final Update update,
                                   final Class<?> entityClass, final boolean upsert, final boolean multi) {
        return updateFirst(query, update, entityClass, collectionName);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    protected <T> void doInsertBatch(String collectionName, Collection<? extends T> batchToSave, MongoWriter<T> writer) {
        Assert.notNull(writer);
        insertAll(batchToSave, tableName);
    }

}


